import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import qs from 'qs'
import router from '/@/router/index'
// import store from '/@/store/index'
import {ElMessage, ElMessageBox} from 'element-plus'
import { Session } from '/@/utils/storage';
import other from '/@/utils/other';

let show_msgBox:Boolean = false; // 弹窗提示

let cancel, promiseArr = {};
const CancelToken = axios.CancelToken;
var myaxios = axios.create({
  // baseURL: baseUrl
  baseURL: import.meta.env.VITE_API_URL,
});
// axios.defaults.withCredentials = true;
//请求拦截器
// myaxios.interceptors.request.use(config => {  
  //发起请求时，取消掉当前正在进行的相同请求
  // if (promiseArr[config.url]) {
  //   promiseArr[config.url]('操作取消');
  //   promiseArr[config.url] = cancel;
  // } else {
  //   promiseArr[config.url] = cancel;
  // }
//   return config;
// }, error => {
//   return Promise.reject(error)
// })

//响应拦截器即异常处理
myaxios.interceptors.response.use(response => {
  return response
}, err => {
  if (err && err.response) {
    switch (err.response.status) {
      case 400:
        err.message = '错误请求'
        break;
      case 401:
        err.message = '未授权，请重新登录'
        break;
      case 403:
        err.message = '拒绝访问'
        break;
      case 404:
        err.message = '请求错误,未找到该资源'
        break;
      case 405:
        err.message = '请求方法未允许'
        break;
      case 408:
        err.message = '请求超时'
        break;
      case 500:
        err.message = '服务器端出错'
        break;
      case 501:
        err.message = '网络未实现'
        break;
      case 502:
        err.message = '网络错误'
        break;
      case 503:
        err.message = '服务不可用'
        break;
      case 504:
        err.message = '网络超时'
        break;
      case 505:
        err.message = 'http版本不支持该请求'
        break;
      default:
        err.message = `连接错误${err.response.status}`
    }
  } else {
    err.message = "连接到服务器失败"
  }
  ElMessage.error(err.message)

  return Promise.resolve(err.response)
});

interface ConfigOptions {
  method: string,
  url: string,
  data: any,
  params: any,
  timeout: number,
  headers: any,
  dataType: string,
  cancelToken: any,
}

function Request (method:string, action:string, params:any, callback?:any, failback?:any, options?:any, type?:string) {
  let url = action;
  // axios传递的请求参数是json格式
  // 如果后端接口要求formData,则post传参是要序列化 qs.stringify(params);
    var default_options: ConfigOptions = {
      method: method,
      // url: process.env.BASE_API + action,
      url: url,
      data: method === 'post' || method === 'put' || method === 'delete' ? params : null,
      params: method === 'get' || method === 'delete' ?  params : null,
      timeout: 15000,
      headers: {},
      dataType: 'json',
      cancelToken: new CancelToken(c => {
        cancel = c
      })
    };

    // 统一增加Authorization请求头, skipToken 跳过增加token
		const token = Session.getToken();
		// if (token && !default_options.headers?.skipToken) {
    if (token) {
			default_options.headers!['Authorization'] = `Bearer ${token}`;
      // if(method == 'get'){
      //   let shopId = localStorage.getItem('shopId');
      //   if( shopId && Number(shopId) > 0  && !default_options.params.shopId){
      //     default_options.params.shopId = shopId;
      //   }        
      // }
		}

		// 统一增加TENANT-ID请求头
		const tenantId = Session.getTenant();
		if (tenantId) {
			default_options.headers!['TENANT_ID'] = tenantId;
		}

		// 请求报文加密
		if (default_options.headers!['Enc-Flag']) {
			const enc = other.encryption(JSON.stringify(default_options.data), import.meta.env.VITE_PWD_ENC_KEY);
			default_options.data = {
				encryption: enc,
			};
		}

    // 如果参数中有formData的属性，就用formData的方式传参
    if(params.hasOwnProperty('formData')){
      default_options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
      default_options.data = qs.stringify(params.formData);
      let opt:any = {};
      for(let key in params){
        if(key != 'formData'){
          opt[key] = params[key];
        }
      }
      default_options.params = opt
    }

    // 扩展参数
    var new_options:object;
    let opt = options;
    if(typeof(callback) == 'object'){
      opt = callback;
    }
    if (opt) {
      new_options = Object.assign({}, default_options, opt);
    } else {
      new_options = default_options;
    }

    // 请求
    return new Promise((resolve, reject) => {
      myaxios(new_options).then(response => {
        const status = Number(response.status) || 200;
        let {code, msg} = response.data; 
        if(type == 'all'){ // 针对有些接口，直接返回内容，没有code,data,msg
          resolve(response.data);
          if(typeof(callback) === 'function'){
            callback(response.data, msg);
          } 
          return;
        }
        // 后台定义 424 针对令牌过去的特殊响应码
        if ((status === 424 || status === 401) && !show_msgBox) {
          show_msgBox = true;
          ElMessageBox.confirm('登录已过期，请点击重新登录', '系统提示', {
              confirmButtonText: '重新登录',
              cancelButtonText: '取消',
              type: 'warning',
              closeOnClickModal: false
            }
          ).then(() => {
            // store.dispatch('LogOut').then(() => {
              // 刷新登录页面，避免多次弹框
              show_msgBox = false;
              // window.location.reload()
              Session.clear(); // 清除浏览器全部临时缓存
				      window.location.href = '/'; // 去登录页
            // })
          }).catch(() => {
            show_msgBox = false;
          });
          if (typeof(failback) === 'function') {
            failback(msg);            
          }
          return
        }
        if (code == 200 || code == 0) {
          resolve(response.data.data);
          if(typeof(callback) === 'function'){
            callback(response.data.data, msg);
          }          
        } else {
          ElMessage.error(msg || '请求失败！');
          if (typeof(failback) === 'function') {
            failback(msg);            
          }
          reject(response.data, msg);
        }
      }).catch(error => {
        // Message.error(error);
        if (typeof(failback) === 'function') {
          failback(error);
        }
        reject(error);
        return;
      })
    });
}

export default Request;